import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import svg.Container;
import svg.JobCanvas;
import svg.JobViewer;
import svg.TaskCanvas;


public class SchedulabilityTestManager 
{
	public static void main(String[] args) throws Exception 
	{
		if(args.length != 1)
		{
			System.out.println("Input file (*.graphml) missing!");
			
			return;
		}
		
		String input = args[0];
		boolean calcPriorities = false;
		
		DataGenerator dataGen = new DataGenerator(input, 1, calcPriorities);
		
		// analysis
		boolean schedulable = ResponseTimeAnalyzer.analyze(dataGen.getTasks());
		
		// simulation
		Simulator.simulate(dataGen.getTasks(), 
				dataGen.getAllJobs(), dataGen.getLCM() * dataGen.getNumberOfCycles());
		
		// sort tasks by name
		Collections.sort(dataGen.getTasks(), new Comparator<Task>() 
			{
				public int compare(Task t1, Task t2) 
				{
					return t1.getName().compareTo(t2.getName());
				}
			});
		
		// writes simulation results to a file
		{
			List<String> data = new ArrayList<String>();
			for(Task task : dataGen.getTasks()) 
			{
				String outStr = task.getName() + " " + task.getWcrt() + "\n";
				data.add(outStr);
			}
			
			dataToFile(new File(input + ".a1.out"), data,
					"Writing simulation results:");
		}
		
		// writes analysis results to a file
		{
			List<String> data = new ArrayList<String>();
			for(Task task : dataGen.getTasks())
			{
				String line = "WCRT for task " + task.getName()
				        + ": VSS: " + task.getWcrt() + "  RTA: " + task.getRta() + "\n";
				data.add(line);
			}

			data.add("Schedulable:" + schedulable);
			
			dataToFile(new File(input + ".a2.out"), data,
					"Writing analysis results:");
		}
		
		// simulation results to an image
		{
			visualize(
			        "Simulating tasks: 1 - "
			                + String.valueOf(dataGen.getTasks().size()),
			                input + ".png", dataGen.getTasks(), dataGen.getLCM()
			                * dataGen.getNumberOfCycles(), 5, 600, 500);
		}
	}
	
	private static void dataToFile(File outputFile, List<String> data, String title)
	{
		System.out.println(title);
		
		FileWriter fstream = null;
		BufferedWriter out = null;
		try
		{
			fstream = new FileWriter(outputFile);
			out = new BufferedWriter(fstream);

			for(String outStr : data)
			{
				out.write(outStr);
				System.out.println(outStr);
			}
		}
		catch (Exception e)
		{
			System.err.println("Error: " + e.getMessage());
		}
		finally
		{
			if(out != null)
			{
				try
	            {
	                out.close();
	            }
	            catch(IOException e)
	            {
	                e.printStackTrace();
	            }
			}
            
			if(fstream != null)
			{
	            try
                {
	                fstream.close();
                }
                catch(IOException e)
                {
	                e.printStackTrace();
                }	
			}
		}
	}
	
	public static void visualize(String title, String filename, 
			ArrayList<Task> tasks, int timeSegment, int scale, int width, int height)
	{
		// create JobViewer
		JobViewer jobViewer = new JobViewer(width, height);
		
		// create BufferedImage and Graphics controller
		BufferedImage image = new BufferedImage(jobViewer.getWidth(), 
				jobViewer.getHeight(), BufferedImage.TYPE_INT_ARGB);
		Graphics2D graphics = image.createGraphics();
    	JobViewer.setGraphicsQuality(graphics);
    	graphics.setColor(Color.WHITE);
    	graphics.fillRect(0, 0, jobViewer.getWidth(), jobViewer.getHeight());
		
    	// create main panel
		Container mainPanel = new Container(10, 40, 
				jobViewer.getWidth() - 10 - 10, 
				jobViewer.getHeight() - 40 - 20);

        // create tasks and jobs
        for(Task task : tasks)
        {
        	TaskCanvas taskPanel = new TaskCanvas(task.getName(), graphics,
        			timeSegment, task.getPeriod(), task.getDeadline(), scale);
        	
        	for(Job job : task.getJobs())
        	{
        		for(Pair p : job.getMergedExecTime())
        		{
        			JobCanvas jobCanvas = new JobCanvas(p.getStart(), 
        					p.getFinish() - p.getStart() + 1, taskPanel);
                	taskPanel.getJobs().add(jobCanvas);	
        		}
        	}
        	
        	mainPanel.getElements().add(taskPanel);
        }
        
        // layout everything
		mainPanel.layout(5);
		
		// make image
		jobViewer.generateImage(title, filename, mainPanel, image, graphics);
	}
}


